package com.caishi.lkx.user.service;

import cn.hutool.core.collection.CollUtil;
import com.caishi.lkx.user.ienum.status.UserStatus;
import com.caishi.lkx.user.model.IUserModel;
import com.caishi.lkx.user.model.UserModel;
import com.caishi.lkx.user.vo.SimpleUserVo;
import com.zzw.common.Fetch;
import com.zzw.common.Wrappers;
import com.zzw.common.entity.BaseService;
import com.zzw.common.entity.impl.BaseEntity;
import com.zzw.common.exception.BizException;
import com.zzw.common.service.NameService;

import com.caishi.lkx.user.dto.LoginDto;
import com.caishi.lkx.user.ienum.type.UserType;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author by keray
 * date:2019/8/1 14:30
 */
public interface IUserService<T extends IUserModel<T>> extends BaseService<T, String>, NameService<T, String> {

    IUserService<UserModel> baseService();

    /**
     * 前端注册
     *
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    T register(@Valid @ModelAttribute LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) throws BizException;

    /**
     * 根据登录信息注册基本用户
     * 自行注册
     *
     * @param userModel
     * @return
     */
    T register(T userModel);


    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2021/4/9 10:57 上午</h3>
     * 用户绑定手机号
     * </p>
     *
     * @param userModel
     * @param phone
     * @return <p> {@link } </p>
     * @throws
     */
    @Transactional(rollbackFor = Exception.class)
    default UserModel bindPhone(UserModel userModel, String phone) {
        IUserService<UserModel> service = baseService();
        return service.bindPhone(userModel, phone);
    }

    @Transactional(rollbackFor = Exception.class)
    default T update(T entity) {
        IUserService<UserModel> service = baseService();
        if (service == this) {
            getMapper().updateById(entity);
            return entity;
        }
        UserModel baseUser = service.update(entity.toUserModel());
        getMapper().updateById(entity.clearUserModelMessage());
        return entity.userInfoCopy(baseUser);
    }

    @Transactional(rollbackFor = Exception.class)
    default T simpleUpdate(T entity) {
        IUserService<UserModel> service = baseService();
        if (service == this) {
            getMapper().updateById(entity);
            return entity;
        }
        UserModel baseUser = service.simpleUpdate(entity.toUserModel());
        getMapper().updateById(entity.clearUserModelMessage());
        return entity.userInfoCopy(baseUser);
    }

    /**
     * 获取用户详情
     *
     * @param userId
     * @return
     */
    default T getUserDetail(String userId, UserModel baseUser) {
        T userModel = this.getMapper().selectById(userId);
        return userModel == null ? null : userModel.userInfoCopy(baseUser);
    }

    default T getUserDetail(String userId) {
        IUserService<UserModel> userService = baseService();
        UserModel base = userService.getById(userId);
        if (userService == this) {
            return (T) base;
        }
        return this.getUserDetail(userId, base);
    }

    default boolean mobileExits(String mobile, String oldMobile) {
        IUserService<UserModel> userService = baseService();
        return userService.mobileExits(mobile, oldMobile);
    }


    default String selectName(String userId) {
        IUserService<UserModel> userService = baseService();
        return Fetch.fetch(userService.selectOne(
                Wrappers.<UserModel>lambdaQuery()
                        .select(UserModel::getName)
                        .eq(UserModel::getId, userId)
        )).then(i -> i == null ? null : i.getName()).getData();
    }


    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2019/11/26 5:00 PM</h3>
     * 获取用户简单信息 仅id，姓名，头像，昵称，性别,username
     * </p>
     *
     * @param userId
     * @return <p> {@link UserModel} </p>
     * @throws
     */
    default SimpleUserVo userSimpleMsg(String userId) {
        IUserService<UserModel> userService = baseService();
        return userService.userSimpleMsg(userId);
    }


    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2021/4/12 10:56 上午</h3>
     * 获取用户role权限
     * </p>
     *
     * @param userId
     * @return <p> {@link String} </p>
     * @throws
     */
    default String getUserRoleName(String userId) {
        IUserService<UserModel> userService = baseService();
        return userService.getUserRoleName(userId);
    }

    default void lockUser(boolean lock, String userId) {
        IUserService<UserModel> userService = baseService();
        userService.lockUser(lock, userId);
    }

    default boolean userIsHaveRole(String userId, UserType userType) {
        IUserService<UserModel> userService = baseService();
        return userService.userIsHaveRole(userId, userType);
    }

    default String getUserMobileById(String userId) {
        IUserService<UserModel> userService = baseService();
        UserModel userModel = userService.selectOne(Wrappers.<UserModel>lambdaQuery().select(UserModel::getMobile).eq(IUserModel::getId, userId));
        return userModel == null ? null : userModel.getMobile();
    }

    default String getUserIdByMobile(String mobile) {
        IUserService<UserModel> userService = baseService();
        return Fetch.fetch(userService.selectOne(Wrappers.<UserModel>lambdaQuery().select(UserModel::getId)
                        .ne(IUserModel::getUserStatus, UserStatus.off)
                        .eq(IUserModel::getMobile, mobile)))
                .then(v -> v == null ? null : v.getId())
                .getData();
    }

    default UserModel getUserByMobile(String mobile) {
        IUserService<UserModel> userService = baseService();
        return userService.selectOne(Wrappers.<UserModel>lambdaQuery().eq(IUserModel::getMobile, mobile).ne(IUserModel::getUserStatus, UserStatus.off));
    }

    @Override
    default String queryName(String s) {
        IUserService<UserModel> userService = baseService();
        UserModel userModel = userService.selectOne(Wrappers.<UserModel>lambdaQuery().select(UserModel::getName).eq(IUserModel::getId, s));
        if (userModel == null) return null;
        return userModel.getName();
    }

    default String getUserNameById(String userId) {
        return this.queryName(userId);
    }

    default List<String> getAllIds() {
        IUserService<UserModel> userService = baseService();
        return userService.selectList(Wrappers.<UserModel>lambdaQuery()).stream().map(BaseEntity::getId).collect(Collectors.toList());
    }


    /**
     * 根据名字模糊匹配，获取用户Ids，可在给定userIds范围内
     *
     * @param userName
     * @param userIds  非必传，指定范围内
     * @return
     */
    default List<String> getIdsByNameAndIds(String userName, List<String> userIds) {
        IUserService<UserModel> userService = baseService();
        return userService.selectList(Wrappers.<UserModel>lambdaQuery()
                .select(UserModel::getId)
                .like(IUserModel::getName, userName)
                .in(CollUtil.isNotEmpty(userIds), BaseEntity::getId, userIds)).stream().map(BaseEntity::getId).collect(Collectors.toList());
    }

    default Map<String, UserModel> getUserMap(List<String> userIds) {
        IUserService<UserModel> userService = baseService();
        return userService.selectList(Wrappers.<UserModel>lambdaQuery().in(BaseEntity::getId, userIds))
                .stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
    }

    default List<UserModel> getUserList(List<String> userIds) {
        IUserService<UserModel> userService = baseService();
        return userService.selectList(Wrappers.<UserModel>lambdaQuery().in(BaseEntity::getId, userIds));
    }

    /**
     * @return java.util.List<com.vip.langrun.user.model.UserModel>
     * @Param: [userPhone]
     * @Author: huangpeng
     * @Date: 2021/11/1 16:52
     * @Description: 通过手机号查询用户 没有就注册
     */
    default List<UserModel> selectListByPhoneOrAdd(List<String> userPhone, String agentUserId) {
        return null;
    }
}
